﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using BHS.TFSChangsetAnalyser.Model;
using BHS.TFSChangsetAnalyser.ViewModel;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using NLog;

namespace BHS.TFSChangsetAnalyser.Import
{
    public class TfsServerChangesetProvider : IChangesetInformationProvider
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

        public IMainWindowViewModel ViewModel { private get; set; }

        public IEnumerable<ChangesetInfo> GetChangesets()
        {
            ICredentials credentials = CreateCredentials();

            List<ChangesetInfo> results = new List<ChangesetInfo>();

            // Add a day to make sure that we get the whole day - we remove the time portion so it will be 00:00
            DateTime endDate = ViewModel.EndDate.AddDays(1);

            VersionSpec versionFrom = new DateVersionSpec(ViewModel.StartDate.Date); // Time portion will be 00:00
            VersionSpec versionTo = new DateVersionSpec(endDate.Date);

            Uri serverPath = new Uri(ViewModel.TfsServerConnectionDetails.TfsServerUrl);

            TfsTeamProjectCollection projectCollection = new TfsTeamProjectCollection(serverPath, credentials);
            projectCollection.EnsureAuthenticated();

            VersionControlServer versionControl = (VersionControlServer)projectCollection.GetService(typeof(VersionControlServer));

            string projectPath = ViewModel.TfsServerConnectionDetails.TfsProjectPath;

            IEnumerable changsets = versionControl.QueryHistory(projectPath, VersionSpec.Latest, 0,
                                                                RecursionType.Full, null, versionFrom, versionTo,
                                                                int.MaxValue, true, true);
            List<Changeset> changsetList = changsets.Cast<Changeset>().ToList();

            foreach (Changeset changeset in changsetList)
            {
                string codeReviewer = string.Empty;
                CheckinNoteFieldValue codeReviewerField = changeset.CheckinNote.Values.FirstOrDefault(note => note.Name == "Code Reviewer");
                if (codeReviewerField != null)
                {
                    codeReviewer = codeReviewerField.Value.Trim();
                }

                // Reviewable changes are either an add or an edit
                int nbrReviewableChanges = changeset.Changes.Count(change => (change.ChangeType == ChangeType.Add || change.ChangeType == ChangeType.Edit));

                ChangesetInfo changesetInfo = new ChangesetInfo
                                                  {
                                                      ChangesetId = changeset.ChangesetId,
                                                      SubmittedDate = changeset.CreationDate,
                                                      Submitter = changeset.Comment,
                                                      Comment = changeset.Comment,
                                                      CodeReviewer = codeReviewer,
                                                      NumberOfChanges = changeset.Changes.Length,
                                                      NumberOfReviewableChanges = nbrReviewableChanges
                                                  };

                results.Add(changesetInfo);
            }

            return results;
        }

        private ICredentials CreateCredentials()
        {
            if (ViewModel.TfsServerConnectionDetails.UseDefaultCredentials)
            {
                Logger.Info("Using Default Credentials");
                return CredentialCache.DefaultNetworkCredentials;
            }

            Logger.Info("Using user provided credentials");
            return new NetworkCredential(ViewModel.TfsServerConnectionDetails.Username,
                                         ViewModel.TfsServerConnectionDetails.Password,
                                         ViewModel.TfsServerConnectionDetails.DomainName);
        }
    }
}
